module mod_lutil
  implicit none
  

  !
  ! Utility class
  !
  ! Contains methods for conversion between various structures, convolusion, automatic loading and saving of maps & power spectra,
  ! timer functions, parameter file usage, output and misc
  !
  ! If used for published results, then please cite these papers: 
  !
  !   Ackerman, Carroll and Wise, Phys. Rev D, vol. 75, Issue 8
  !   Groeneboom and Eriksen, 2008, eprint arXiv:0807.2242
  !   Tim Davis, 2005, ACM Trans. Math. Softw. vol 31 no 4
  !
  ! (c) Nicolaas E. Groeneboom
  !     leuat@irio.co.uk
  !     http://www.irio.co.uk
  !
  

  real :: timer_start, timer_add, timer_percent, timer_end, timer_count, timer_addpercent, timer_total
 
contains  

  ! Timer utilities. 
  ! 
  ! Use lutil_timer_init(number of iterations, percent to produce output) before a loop
  ! call lutil_timer_count for each iteration
  !
  subroutine lutil_timer_init(count, percent)
    implicit none

    integer, intent(in) :: count
    real,     intent(in) :: percent
    
    timer_percent = 0.d0
    timer_add = 100.d0/(real(count))
    timer_addpercent = percent
    timer_count = 0
    timer_total = count
    call cpu_time(timer_end)
    
 end subroutine lutil_timer_init


  subroutine lutil_timer_count
    implicit none

    integer :: min, sec

    timer_percent = timer_percent + timer_add
    timer_count   = timer_count   + timer_add
    
    !write(*,*) timer_count
    if (timer_count>=timer_addpercent) then
       timer_start = timer_end
       call cpu_time(timer_end) 
       timer_count = 0.d0
       sec = ((timer_end-timer_start))*(100.d0 - timer_percent)
       min = int(sec/60.d0)
       sec = sec - min*60
       write(*,*)  int(timer_percent),'%', min, sec
    end if
    
  end subroutine lutil_timer_count


! Output routines



  ! *****************************************************************************************
  !
  ! Routine for reading one parameter from a parameter file
  !     Example usage:   call get_parameter(21, "parfile.txt", "NSIDE", par_int=nside)
  !
  ! *****************************************************************************************
  subroutine lutil_get_parameter(unit, parfile, parname, par_int, par_char, &
       & par_string, par_sp, par_dp, par_lgt)
    implicit none

    integer,      intent(in)  :: unit
    character(len=*),  intent(in)  :: parfile, parname
    integer,      intent(out), optional :: par_int
    logical,      intent(out), optional :: par_lgt
    character(len=1),  intent(out), optional :: par_char
    character(len=*),  intent(out), optional :: par_string
    real,          intent(out), optional :: par_sp
    double precision,          intent(out), optional :: par_dp


    integer        :: i
    character(len=128)  :: string, variable, value
    character(len=1)    :: equals


    open(unit, file=trim(parfile))

    do while (.true.)
       read(unit,*,end=1) string

       if (string(1:1)=='#') cycle

       backspace(unit)
       read(unit,*) variable, equals, value

       if (trim(variable) == trim(parname)) then

          if (present(par_int)) then
             read(value,*) par_int
          else if (present(par_char)) then
             read(value,*) par_char
          else if (present(par_string)) then
             read(value,'(a)') par_string
          else if (present(par_sp)) then
             read(value,*) par_sp
          else if (present(par_dp)) then
             read(value,*) par_dp
          else if (present(par_lgt)) then
             read(value,*) par_lgt
          end if

          close(unit)
          return

       end if

    end do

1   write(*,*) 'GET_PARAMETER:    Critical error -- parameter not found'
    write(*,*) 'GET_PARAMETER:       Parameter file = ', trim(parfile)
    write(*,*) 'GET_PARAMETER:       Parameter name = ', trim(parname)

    close(unit)
    stop

  end subroutine lutil_get_parameter





end module mod_lutil
